/**
 * 内存泄露修复工具
 * 提供快速的内存清理和监控功能
 */

interface TimerInfo {
  id: NodeJS.Timeout;
  created: number;
  delay: number;
  stack?: string;
  type: 'timeout' | 'interval';
}

interface ListenerInfo {
  target: EventTarget;
  event: string;
  handler: EventListener;
  options?: boolean | AddEventListenerOptions;
  created: number;
  stack?: string;
}

export class MemoryLeakFixer {
  private static instance: MemoryLeakFixer;
  private timers = new Map<NodeJS.Timeout, TimerInfo>();
  private listeners = new Map<string, ListenerInfo>();
  private abortControllers = new Set<AbortController>();
  private audioElements = new Set<HTMLAudioElement>();
  private isMonitoring = false;
  private monitorInterval?: NodeJS.Timeout;

  static getInstance(): MemoryLeakFixer {
    if (!MemoryLeakFixer.instance) {
      MemoryLeakFixer.instance = new MemoryLeakFixer();
    }
    return MemoryLeakFixer.instance;
  }

  /**
   * 开始监控内存使用情况
   */
  startMonitoring(intervalMs = 10000): void {
    if (this.isMonitoring) return;
    
    this.isMonitoring = true;
    // console.log('🔍 内存泄露监控已启动');

    this.monitorInterval = setInterval(() => {
      // this.reportMemoryStatus();
      this.checkForLeaks();
    }, intervalMs);
  }

  /**
   * 停止监控
   */
  stopMonitoring(): void {
    if (this.monitorInterval) {
      clearInterval(this.monitorInterval);
      this.monitorInterval = undefined;
    }
    this.isMonitoring = false;
    // console.log('🔍 内存泄露监控已停止');
  }

  /**
   * 安全的 setTimeout，会自动追踪和清理
   */
  setTimeout(callback: () => void, delay: number): NodeJS.Timeout {
    const timer = setTimeout(() => {
      this.timers.delete(timer);
      try {
        callback();
      } catch (error) {
        console.error('Timer callback error:', error);
      }
    }, delay);

    this.timers.set(timer, {
      id: timer,
      created: Date.now(),
      delay,
      stack: new Error().stack,
      type: 'timeout'
    });

    return timer;
  }

  /**
   * 安全的 setInterval，会自动追踪和清理
   */
  setInterval(callback: () => void, delay: number): NodeJS.Timeout {
    const timer = setInterval(() => {
      try {
        callback();
      } catch (error) {
        console.error('Interval callback error:', error);
      }
    }, delay);

    this.timers.set(timer, {
      id: timer,
      created: Date.now(),
      delay,
      stack: new Error().stack,
      type: 'interval'
    });

    return timer;
  }

  /**
   * 清理指定的定时器
   */
  clearTimer(timer: NodeJS.Timeout): void {
    const info = this.timers.get(timer);
    if (info) {
      if (info.type === 'interval') {
        clearInterval(timer);
      } else {
        clearTimeout(timer);
      }
      this.timers.delete(timer);
    }
  }

  /**
   * 安全的事件监听器添加
   */
  addEventListener(
    target: EventTarget,
    event: string,
    handler: EventListener,
    options?: boolean | AddEventListenerOptions
  ): () => void {
    target.addEventListener(event, handler, options);
    
    const listenerId = `${target.constructor.name}-${event}-${Date.now()}-${Math.random()}`;
    this.listeners.set(listenerId, {
      target,
      event,
      handler,
      options,
      created: Date.now(),
      stack: new Error().stack
    });

    // 返回清理函数
    return () => {
      target.removeEventListener(event, handler, options);
      this.listeners.delete(listenerId);
    };
  }

  /**
   * 创建可中断的请求控制器
   */
  createAbortController(): AbortController {
    const controller = new AbortController();
    this.abortControllers.add(controller);

    // 当请求完成时自动清理
    controller.signal.addEventListener('abort', () => {
      this.abortControllers.delete(controller);
    });

    return controller;
  }

  /**
   * 注册音频元素进行管理
   */
  registerAudioElement(audio: HTMLAudioElement): () => void {
    this.audioElements.add(audio);

    // 返回清理函数
    return () => {
      this.cleanupAudioElement(audio);
    };
  }

  /**
   * 清理音频元素
   */
  private cleanupAudioElement(audio: HTMLAudioElement): void {
    try {
      audio.pause();
      audio.currentTime = 0;
      audio.src = '';
      audio.load();
      this.audioElements.delete(audio);
    } catch (error) {
      // console.warn('清理音频元素失败:', error);
      console.error('cleanup audio element failed', error);
    }
  }

  /**
   * 清理所有定时器
   */
  clearAllTimers(): void {
    // console.log(`🧹 清理 ${this.timers.size} 个定时器`);
    
    this.timers.forEach((info, timer) => {
      try {
        if (info.type === 'interval') {
          clearInterval(timer);
        } else {
          clearTimeout(timer);
        }
      } catch (error) {
        // console.warn('清理定时器失败:', error);
        console.error('cleanup timer failed', error);
      }
    });
    
    this.timers.clear();
  }

  /**
   * 清理所有事件监听器
   */
  clearAllEventListeners(): void {
    // console.log(`🧹 清理 ${this.listeners.size} 个事件监听器`);
    
    this.listeners.forEach((info, id) => {
      try {
        info.target.removeEventListener(info.event, info.handler, info.options);
      } catch (error) {
        // console.warn('清理事件监听器失败:', error);
        console.error('cleanup event listener failed', error);
      }
    });
    
    this.listeners.clear();
  }

  /**
   * 中断所有请求
   */
  abortAllRequests(): void {
    // console.log(`🧹 中断 ${this.abortControllers.size} 个请求`);
    
    this.abortControllers.forEach(controller => {
      try {
        controller.abort();
      } catch (error) {
        // console.warn('中断请求失败:', error);
        console.error('abort request failed', error);
      }
    });
    
    this.abortControllers.clear();
  }

  /**
   * 清理所有音频元素
   */
  clearAllAudioElements(): void {
    // console.log(`🧹 清理 ${this.audioElements.size} 个音频元素`);
    
    this.audioElements.forEach(audio => {
      this.cleanupAudioElement(audio);
    });
  }

  /**
   * 全面清理所有资源
   */
  cleanup(): void {
    // console.log('🧹 开始全面内存清理...');
    
    this.clearAllTimers();
    this.clearAllEventListeners();
    this.abortAllRequests();
    this.clearAllAudioElements();
    this.stopMonitoring();
    
    // console.log('✅ 内存清理完成');
  }

  /**
   * 报告内存使用状态
   */
  private reportMemoryStatus(): void {
    // const stats = {
    //   timers: this.timers.size,
    //   listeners: this.listeners.size,
    //   requests: this.abortControllers.size,
    //   audioElements: this.audioElements.size
    // };

    // if ((performance as any).memory) {
    //   // const memory = {
    //   //   used: Math.round((performance as any).memory.usedJSHeapSize / 1024 / 1024),
    //   //   total: Math.round((performance as any).memory.totalJSHeapSize / 1024 / 1024),
    //   //   limit: Math.round((performance as any).memory.jsHeapSizeLimit / 1024 / 1024)
    //   // };

    //   // console.log('📊 内存状态:', { ...stats, memory });
    // } else {
    //   // console.log('📊 资源状态:', stats);
    // }
  }

  /**
   * 检查潜在的泄露
   */
  private checkForLeaks(): void {
    const now = Date.now();
    const longRunningThreshold = 60000; // 60秒

    // 检查长时间运行的定时器
    const longRunningTimers = Array.from(this.timers.values()).filter(
      timer => now - timer.created > longRunningThreshold
    );

    if (longRunningTimers.length > 0) {
      // console.warn(`⚠️ 发现 ${longRunningTimers.length} 个长时间运行的定时器`, longRunningTimers);
      console.error(`found ${longRunningTimers.length} long-running timers`, longRunningTimers);
    }

    // 检查长时间存在的监听器
    const longRunningListeners = Array.from(this.listeners.values()).filter(
      listener => now - listener.created > longRunningThreshold
    );

    if (longRunningListeners.length > 0) {
      // console.warn(`⚠️ 发现 ${longRunningListeners.length} 个长时间存在的监听器`, longRunningListeners);
      console.error(`found ${longRunningListeners.length} long-running listeners`, longRunningListeners);
    }

    // 检查资源数量阈值
    if (this.timers.size > 20) {
      // console.warn(`⚠️ 定时器数量过多: ${this.timers.size}`);
      console.error(`too many timers: ${this.timers.size}`);
    }

    if (this.listeners.size > 50) {
      // console.warn(`⚠️ 事件监听器数量过多: ${this.listeners.size}`);
      console.error(`too many event listeners: ${this.listeners.size}`);
    }

    if (this.audioElements.size > 10) {
      // console.warn(`⚠️ 音频元素数量过多: ${this.audioElements.size}`);
      console.error(`too many audio elements: ${this.audioElements.size}`);
    }
  }

  /**
   * 获取详细的资源统计
   */
  getDetailedStats() {
    return {
      timers: Array.from(this.timers.values()).map(timer => ({
        type: timer.type,
        delay: timer.delay,
        age: Date.now() - timer.created,
        stack: timer.stack?.split('\n').slice(0, 3).join('\n')
      })),
      listeners: Array.from(this.listeners.values()).map(listener => ({
        target: listener.target.constructor.name,
        event: listener.event,
        age: Date.now() - listener.created,
        stack: listener.stack?.split('\n').slice(0, 3).join('\n')
      })),
      requests: this.abortControllers.size,
      audioElements: this.audioElements.size
    };
  }
}

// 导出单例实例
export const memoryLeakFixer = MemoryLeakFixer.getInstance();

// 开发环境下自动启动监控
if (process.env.NODE_ENV === 'development') {
  memoryLeakFixer.startMonitoring();
}

// 页面卸载时自动清理
if (typeof window !== 'undefined') {
  window.addEventListener('beforeunload', () => {
    memoryLeakFixer.cleanup();
  });

  // 提供全局访问
  (window as any).memoryLeakFixer = memoryLeakFixer;
}

// 导出便捷函数
export const safeSetTimeout = memoryLeakFixer.setTimeout.bind(memoryLeakFixer);
export const safeSetInterval = memoryLeakFixer.setInterval.bind(memoryLeakFixer);
export const safeAddEventListener = memoryLeakFixer.addEventListener.bind(memoryLeakFixer);
export const createAbortController = memoryLeakFixer.createAbortController.bind(memoryLeakFixer);
export const registerAudio = memoryLeakFixer.registerAudioElement.bind(memoryLeakFixer); 